package core;

//import java.io.BufferedInputStream;
//import java.io.BufferedOutputStream;
//import java.io.File;
//import java.io.FileInputStream;
//import java.io.FileOutputStream;
//import java.io.IOException;
//import java.io.Reader;
//import java.io.StringReader;
//import java.sql.Blob;
//import java.sql.PreparedStatement;
//import java.sql.ResultSet;
//import java.util.Iterator;
//
//import org.dom4j.Document;
//import org.dom4j.DocumentException;
//import org.dom4j.Element;
//
//import xml.MyDom4j;
//
//import dataBase.DbConnection;

public class Base64 {

	// static int unnecessaryByteNum;

	static char base64_alphabet[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
			'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
			'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
			'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
			'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
			'8', '9', '+', '/', '=' };

	static byte debase64_alphabet[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1,
			62, // +
			-1, -1,
			-1,
			63, // /
			52, 53, 54, 55, 56, 57, 58, 59,
			60,
			61, // 0~9
			-1, -1,
			-1,
			64, // =
			-1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
			13,
			14, // A~Z
			15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1,
			26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
			38, // a~z
			39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1,
			-1 };

	// static void Setmany(int num) {
	// unnecessaryByteNum = num;
	// }
	//
	// static int Getmany() {
	// return unnecessaryByteNum;
	// }

	private static byte[] Encode(byte[] b, int n) {

		byte b1 = (byte) 0;
		byte b2 = (byte) 0;
		byte b3 = (byte) 0;
		byte b4 = (byte) 0;
		if (n == 0) {
			b1 = (byte) ((b[0] & 252) >>> 2);
			b2 = (byte) (((b[0] & 3) << 4) | ((b[1] & 240) >>> 4));
			b3 = (byte) (((b[1] & 15) << 2) | ((b[2] & 192) >>> 6));
			b4 = (byte) (b[2] & 63);
		}
		if (n == 1) {
			b1 = (byte) ((b[0] & 252) >>> 2);
			b2 = (byte) ((b[0] & 3) << 4);
			b3 = (byte) (64);
			b4 = (byte) (64);
		}

		if (n == 2) {
			b1 = (byte) ((b[0] & 252) >>> 2);
			b2 = (byte) (((b[0] & 3) << 4) | ((b[1] & 240) >>> 4));
			b3 = (byte) ((b[1] & 15) << 2);
			b4 = (byte) (64);
		}

		byte[] rb = new byte[4];
		rb[0] = b1;
		rb[1] = b2;
		rb[2] = b3;
		rb[3] = b4;
		return rb;
	}

	static byte[] EncodeBase64(byte[] buffer, int count) {
		byte[] sb = null;
		if (count % 3 == 0) {

			// System.out.println("3x"+" "+((int)(count/3))*4);
			sb = new byte[count * 4 / 3];
			byte[] b = new byte[3];
			int j = 0;
			for (int i = 0; i <= count - 3; i += 3) {
				b[0] = buffer[i];
				b[1] = buffer[i + 1];
				b[2] = buffer[i + 2];
				byte[] rb = Encode(b, 0);
				sb[j] = (byte) base64_alphabet[rb[0]];
				sb[j + 1] = (byte) base64_alphabet[rb[1]];
				sb[j + 2] = (byte) base64_alphabet[rb[2]];
				sb[j + 3] = (byte) base64_alphabet[rb[3]];
				j += 4;
			}
			return sb;
		}
		if (count % 3 == 1) {

			// System.out.println("3x+1"+" "+((int)(count/3)+1)*4);
			sb = new byte[((int) (count / 3) + 1) * 4];
			byte[] b = new byte[3];
			int j = 0;
			for (int i = 0; i <= count - 3; i += 3) {
				b[0] = buffer[i];
				b[1] = buffer[i + 1];
				b[2] = buffer[i + 2];
				byte[] rb = Encode(b, 0);
				sb[j] = (byte) base64_alphabet[rb[0]];
				sb[j + 1] = (byte) base64_alphabet[rb[1]];
				sb[j + 2] = (byte) base64_alphabet[rb[2]];
				sb[j + 3] = (byte) base64_alphabet[rb[3]];
				j += 4;
			}

			b[0] = buffer[count - 1];
			b[1] = (byte) 0;
			b[2] = (byte) 0;
			byte[] rb = Encode(b, 1);
			sb[j] = (byte) base64_alphabet[rb[0]];
			sb[j + 1] = (byte) base64_alphabet[rb[1]];
			sb[j + 2] = (byte) base64_alphabet[rb[2]];
			sb[j + 3] = (byte) base64_alphabet[rb[3]];

			return sb;
		}
		if (count % 3 == 2) {

			// System.out.println("3x+2"+" "+((int)(count/3)+1)*4);
			sb = new byte[((int) (count / 3) + 1) * 4];
			byte[] b = new byte[3];
			int j = 0;
			for (int i = 0; i <= count - 3; i += 3) {
				b[0] = buffer[i];
				b[1] = buffer[i + 1];
				b[2] = buffer[i + 2];
				byte[] rb = Encode(b, 0);
				sb[j] = (byte) base64_alphabet[rb[0]];
				sb[j + 1] = (byte) base64_alphabet[rb[1]];
				sb[j + 2] = (byte) base64_alphabet[rb[2]];
				sb[j + 3] = (byte) base64_alphabet[rb[3]];
				j += 4;
			}

			b[0] = buffer[count - 2];
			b[1] = buffer[count - 1];
			b[2] = (byte) 0;
			byte[] rb = Encode(b, 2);
			sb[j] = (byte) base64_alphabet[rb[0]];
			sb[j + 1] = (byte) base64_alphabet[rb[1]];
			sb[j + 2] = (byte) base64_alphabet[rb[2]];
			sb[j + 3] = (byte) base64_alphabet[rb[3]];
			return sb;
		}
		return sb;
	}

	private static byte[] Decode(byte[] rb, int n) {

		byte[] b = null;
		if (n == 0) {
			byte b1 = (byte) (((rb[0] & 63) << 2) | (rb[1] & 48) >>> 4);
			byte b2 = (byte) (((rb[1] & 15) << 4) | (rb[2] & 60) >>> 2);
			byte b3 = (byte) (((rb[2] & 3) << 6) | (rb[3] & 63));
			b = new byte[3];
			b[0] = b1;
			b[1] = b2;
			b[2] = b3;
		}
		if (n == 1) {
			byte b1 = (byte) (((rb[0] & 63) << 2) | (rb[1] & 48) >>> 4);
			byte b2 = (byte) (((rb[1] & 15) << 4) | (rb[2] & 60) >>> 2);
			b = new byte[2];
			b[0] = b1;
			b[1] = b2;
		}

		if (n == 2) {
			byte b1 = (byte) (((rb[0] & 63) << 2) | (rb[1] & 48) >>> 4);
			b = new byte[1];
			b[0] = b1;
		}
		return b;
	}

	static byte[] DecodeBase64(byte[] base64Buffer, int count, int trim) {

		byte[] buffer = new byte[count / 4 * 3 - trim];
		int n = 0;
		byte[] b64 = new byte[4];
		int j = 0;
		for (int i = 0; i <= count - 4; i += 4) {
			b64[0] = debase64_alphabet[base64Buffer[i]];
			b64[1] = debase64_alphabet[base64Buffer[i + 1]];
			b64[2] = debase64_alphabet[base64Buffer[i + 2]];
			b64[3] = debase64_alphabet[base64Buffer[i + 3]];

			if (b64[3] == (byte) (64)) {
				n = 1;
			}

			if (b64[2] == (byte) (64) && b64[3] == (byte) (64)) {
				n = 2;
			}

			byte[] rb = Decode(b64, n);

			if (n == 0) {
				buffer[j] = (byte) rb[0];
				buffer[j + 1] = (byte) rb[1];
				buffer[j + 2] = (byte) rb[2];
				j += 3;
			}
			if (n == 1) {
				buffer[j] = (byte) rb[0];
				buffer[j + 1] = (byte) rb[1];
				j += 2;
				// Setmany(1);
			}
			if (n == 2) {
				buffer[j] = (byte) rb[0];
				j += 1;
				// Setmany(2);
			}

		}
		return buffer;
	}

	public static char[] EncodeBase64toChar(byte[] buffer, int count) {
		char[] sb = null;
		if (count % 3 == 0) {

			// System.out.println("3x"+" "+((int)(count/3))*4);
			sb = new char[count * 4 / 3];
			byte[] b = new byte[3];
			int j = 0;
			for (int i = 0; i <= count - 3; i += 3) {
				b[0] = buffer[i];
				b[1] = buffer[i + 1];
				b[2] = buffer[i + 2];
				byte[] rb = Encode(b, 0);
				sb[j] = (char) base64_alphabet[rb[0]];
				sb[j + 1] = (char) base64_alphabet[rb[1]];
				sb[j + 2] = (char) base64_alphabet[rb[2]];
				sb[j + 3] = (char) base64_alphabet[rb[3]];
				j += 4;
			}
			return sb;
		}
		if (count % 3 == 1) {

			// System.out.println("3x+1"+" "+((int)(count/3)+1)*4);
			sb = new char[((int) (count / 3) + 1) * 4];
			byte[] b = new byte[3];
			int j = 0;
			for (int i = 0; i <= count - 3; i += 3) {
				b[0] = buffer[i];
				b[1] = buffer[i + 1];
				b[2] = buffer[i + 2];
				byte[] rb = Encode(b, 0);
				sb[j] = (char) base64_alphabet[rb[0]];
				sb[j + 1] = (char) base64_alphabet[rb[1]];
				sb[j + 2] = (char) base64_alphabet[rb[2]];
				sb[j + 3] = (char) base64_alphabet[rb[3]];
				j += 4;
			}

			b[0] = buffer[count - 1];
			b[1] = (byte) 0;
			b[2] = (byte) 0;
			byte[] rb = Encode(b, 1);
			sb[j] = (char) base64_alphabet[rb[0]];
			sb[j + 1] = (char) base64_alphabet[rb[1]];
			sb[j + 2] = (char) base64_alphabet[rb[2]];
			sb[j + 3] = (char) base64_alphabet[rb[3]];

			return sb;
		}
		if (count % 3 == 2) {

			// System.out.println("3x+2"+" "+((int)(count/3)+1)*4);
			sb = new char[((int) (count / 3) + 1) * 4];
			byte[] b = new byte[3];
			int j = 0;
			for (int i = 0; i <= count - 3; i += 3) {
				b[0] = buffer[i];
				b[1] = buffer[i + 1];
				b[2] = buffer[i + 2];
				byte[] rb = Encode(b, 0);
				sb[j] = (char) base64_alphabet[rb[0]];
				sb[j + 1] = (char) base64_alphabet[rb[1]];
				sb[j + 2] = (char) base64_alphabet[rb[2]];
				sb[j + 3] = (char) base64_alphabet[rb[3]];
				j += 4;
			}

			b[0] = buffer[count - 2];
			b[1] = buffer[count - 1];
			b[2] = (byte) 0;
			byte[] rb = Encode(b, 2);
			sb[j] = (char) base64_alphabet[rb[0]];
			sb[j + 1] = (char) base64_alphabet[rb[1]];
			sb[j + 2] = (char) base64_alphabet[rb[2]];
			sb[j + 3] = (char) base64_alphabet[rb[3]];
			return sb;
		}
		return sb;
	}

	public static byte[] DecodeBase64FromChar(char[] charBuffer, int count,
			int trim) {

		byte[] buffer = new byte[(count / 4 * 3) - trim];
		int n = 0;
		byte[] b64 = new byte[4];
		int j = 0;
		for (int i = 0; i <= count - 4; i += 4) {
			b64[0] = debase64_alphabet[charBuffer[i]];
			b64[1] = debase64_alphabet[charBuffer[i + 1]];
			b64[2] = debase64_alphabet[charBuffer[i + 2]];
			b64[3] = debase64_alphabet[charBuffer[i + 3]];

			if (b64[3] == (byte) (64)) {
				n = 1;
			}

			if (b64[2] == (byte) (64) && b64[3] == (byte) (64)) {
				n = 2;
			}

			byte[] rb = Decode(b64, n);

			if (n == 0) {
				buffer[j] = (byte) rb[0];
				buffer[j + 1] = (byte) rb[1];
				buffer[j + 2] = (byte) rb[2];
				j += 3;
			}
			if (n == 1) {
				buffer[j] = (byte) rb[0];
				buffer[j + 1] = (byte) rb[1];
				j += 2;
				// Setmany(1);
			}
			if (n == 2) {
				buffer[j] = (byte) rb[0];
				j += 1;
				// Setmany(2);
			}

		}
		return buffer;
	}

	public static byte[] DecodeBase64String(String text) {

		int count = text.length();
		int trim = 0;
		char[] charBuffer = text.toCharArray();
		if (count > 0) {
			for (int i = 0; i < 2; i++) {
				if ((count - 1 - i) >= 0) {
					if (charBuffer[count - 1 - i] == '=') {
						trim++;
					}
				}
			}
		}
		byte[] buffer = DecodeBase64FromChar(charBuffer, count, trim);
		return buffer;
	}

	public static void main(String[] args) throws Exception {
		// int id[] = new int[] { 1, 2, 3, 4 };
		// FinalTestIntoXml(id, "s.xml");
		// FinalTestFromXml("s", "jpg");
	}
}

// public static void FinalTestIntoXml(int id[], String filename)
// throws DocumentException, Exception {
// DbConnection dbCon = new DbConnection("MSSQL", "sa", "123456");
// Document doc = MyDom4j.CreatDocumentRoot("root");
//
// try {
// dbCon.Connection();
// String sql = "SELECT IMAGE FROM IMAGE WHERE ID=?";
// PreparedStatement ps = dbCon.GetPreparedStatement(sql);
// for (int i = 0; i < id.length; i++) {
// ps.setInt(1, id[i]);
//
// ResultSet rs = ps.executeQuery();
// while (rs.next()) {
// Blob blob = rs.getBlob(1);
// BufferedInputStream bis = new BufferedInputStream(
// blob.getBinaryStream());
// byte[] buffer = new byte[3072];
//
// char[] charBuffer;
//
// StringBuffer strBuffer = new StringBuffer();
//
// int count = -1;
// while ((count = bis.read(buffer, 0, 3072)) != -1) {
// charBuffer = EncodeBase64toChar(buffer, count);
// strBuffer.append(charBuffer);
// }
//
// Element root = doc.getRootElement();
// Element image = root.addElement("image");
// image.setText(strBuffer.toString());
// }
// MyDom4j.CreatXML(doc, "D:" + File.separatorChar, filename);
//
// }
// } finally {
// dbCon.CloseConnection();
// }
// }
//
// public static void FinalTestFromXml(String filename, String type)
// throws DocumentException, Exception {
// Document doc = MyDom4j.Read("D:" + File.separatorChar + "s.xml");
// Element root = doc.getRootElement();
// char[] charBuffer = new char[4 * 1024];
// int i = 1;
// for (@SuppressWarnings("unchecked")
// Iterator<Element> it = root.elementIterator("image"); it.hasNext();) {
// Element image = it.next();
// String xmlText = image.getText();
// int count = -1;
//
// Reader reader = new StringReader(xmlText.toString());
// BufferedOutputStream bos = new BufferedOutputStream(
// new FileOutputStream("d:" + File.separatorChar + "Decode"
// + filename + i + "." + type));
// int size = xmlText.length() < 4 * 1024 ? xmlText.length()
// : 4 * 1024;
//
// while ((count = reader.read(charBuffer, 0, size)) != -1) {
// byte[] DecodeBuffer = DecodeBase64FromChar(charBuffer, count);
// bos.write(DecodeBuffer, 0, DecodeBuffer.length - Getmany());
// }
// Setmany(0);
// bos.flush();
// bos.close();
// i++;
// }
//
// }